package test.monitors;

import basemod.ReflectionHacks;
import basemod.interfaces.*;
import com.megacrit.cardcrawl.cards.AbstractCard;
import com.megacrit.cardcrawl.cards.CardGroup;
import com.megacrit.cardcrawl.cards.Soul;
import com.megacrit.cardcrawl.cards.SoulGroup;
import com.megacrit.cardcrawl.characters.AbstractPlayer;
import com.megacrit.cardcrawl.core.Settings;
import com.megacrit.cardcrawl.dungeons.AbstractDungeon;
import com.megacrit.cardcrawl.rooms.AbstractRoom;
import test.CaptainCore;
import test.actions.ShadowAction;
import test.cards.BaseCaptainCard;
import test.patches.TagsPatch;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;

public class SeaMonitor implements OnStartBattleSubscriber, StartGameSubscriber {

    public static final ArrayList<Float> X_OFFSET = new ArrayList<>(Arrays.asList(-2.7f,-2.1f,-1.5f,-0.9f,-0.3f,0.3f,0.9f,1.5f,2.1f,2.7f));
    public static final float X_OFFSET_NEGATIVE_1=-3.5f;
    public static final float X_OFFSET_11=3.5f;
    public static final float Y_OFFSET = 90.0f;
    public static ArrayList<Sea> seaList;
    public static ArrayList<Float> BLANK_SEA_POSITIONS_X;
    public static float INDEX_NEGATIVE_1;
    public static float INDEX_10;
    public static float BLANK_SEA_POSITIONS_Y;
    public static final int MAX_HAND_SIZE=10;
    public static final float CARD_SCALA=0.75f;

    public static void initBlankSeaPositions() {
        BLANK_SEA_POSITIONS_X = new ArrayList<>();
        for(int i = 0; i < MAX_HAND_SIZE; i++) {
            float xPos = Settings.WIDTH / 2.0F + AbstractCard.IMG_WIDTH_S * X_OFFSET.get(i);
            BLANK_SEA_POSITIONS_X.add(xPos);
        }
        INDEX_NEGATIVE_1 = Settings.WIDTH / 2.0F+AbstractCard.IMG_WIDTH_S * X_OFFSET_NEGATIVE_1;
        INDEX_10 = Settings.WIDTH / 2.0F+AbstractCard.IMG_WIDTH_S * X_OFFSET_11;
        BLANK_SEA_POSITIONS_Y = Settings.scale * Y_OFFSET;
    }

    public static void initializeSea(){
        seaList = new ArrayList<>();
        for(int i=0;i<MAX_HAND_SIZE;i++){
            seaList.add(new Sea(null,i,i+1));
        }
    }

    public static void resetSea(){
        for(int i=0;i<MAX_HAND_SIZE;i++){
            Sea sea=seaList.get(i);
            sea.card=null;
            sea.coordinate=i+1;
        }
    }

    @Override
    public void receiveOnBattleStart(AbstractRoom abstractRoom) {
        resetSea();
    }

    @Override
    public void receiveStartGame() {
        initBlankSeaPositions();
        initializeSea();
        //AbstractPlayer
    }

    public static class Sea{
        public AbstractCard card;
        public int index;
        public int coordinate;

        public Sea(AbstractCard card, int index,int coordinate){
            this.card = card;
            this.index = index;
            this.coordinate = coordinate;
        }

        public Sea deepCopy(){
            Sea copy = new Sea(card,index,coordinate);
            return copy;
        }
    }

    public static ArrayList<Sea> deepCopy() {
        ArrayList<Sea> copy = new ArrayList<>();
        for(int i=0;i<MAX_HAND_SIZE;i++){
            copy.add(seaList.get(i).deepCopy());
        }
        return copy;
    }

    public static void swapCard(AbstractCard card1,AbstractCard card2){
        Sea sea1=getSeaByCard(card1);
        Sea sea2=getSeaByCard(card2);
        sea1.card=card2;
        sea2.card=card1;
        //sortHandCardGroup();
        //AbstractDungeon.player.hand.refreshHandLayout();
    }

    public static boolean contains(AbstractCard card){
        for(Sea sea : seaList){
            if(sea.card!=null&&sea.card.equals(card)){
                return true;
            }
        }
        return false;
    }

    public static Sea getFirstSeaWithoutCardIndex(){
        for(Sea sea : seaList){
            if(sea.card==null){
                return sea;
            }
        }
        return null;
    }

    public static Sea getSeaByCard(AbstractCard card){
        for (Sea sea : seaList){
            if(sea.card!=null&&sea.card.equals(card)){
                return sea;
            }
        }
        return null;
    }

    public static void onRemoveFromHand(AbstractCard __instance) {
        Sea sea = getSeaByCard(__instance);
        sea.card=null;
        customHandLeftMove();
        sortHandCardGroup();
    }

    public static Soul soulContains(AbstractCard card){
        if(card==null){
            return null;
        }
        ArrayList<Soul> souls = ReflectionHacks.getPrivate(AbstractDungeon.currMapNode.room.souls, SoulGroup.class, "souls");
        for(Soul soul:souls){
            if(soul.card != null&&soul.card.equals(card)){
                return soul;
            }
        }
        return null;
    }

    public static void onAddFromHand(AbstractCard __instance) {
        Sea sea=SeaMonitor.getFirstSeaWithoutCardIndex();
        if(sea!=null){
            sea.card=__instance;
        }
        sortHandCardGroup();
//        if(__instance instanceof BaseCaptainCard){
//            ((BaseCaptainCard) __instance).onAddToHand();
//        }
    }


    public static void customHandLeftMove(){
        for(AbstractCard c: AbstractDungeon.player.hand.group){
            if(TagsPatch.CardFieldPatch.hasAnchor.get(c)){
                continue;
            }
            Sea sea = getFirstSeaWithoutCardIndex();
            if(sea.index<getSeaByCard(c).index){
                getSeaByCard(c).card=null;
                sea.card=c;
            }
        }
    }

    public static void sortHandCardGroup(){
        AbstractDungeon.player.hand.group.sort(Comparator.comparingInt(c -> getSeaByCard(c).index));
    }
    
}
